package com.itheima.health.service.impl;

import com.itheima.health.dao.ReportDao;
import com.itheima.health.service.ReportService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import com.itheima.health.pojo.entity.HotSetmeal;
import com.itheima.health.pojo.entity.Number;
import com.itheima.health.pojo.entity.Order;
import com.itheima.health.service.ReportService;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.itheima.health.pojo.entity.SetmealOrderInfo;
import com.itheima.health.pojo.vo.SetmealReportVO;
import com.itheima.health.service.ReportService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ReportServiceImpl implements ReportService {

    @Autowired
    private ReportDao reportDao;


    @Override
    public SetmealReportVO getSetmealReport() {
        //获取预定信息
        List<SetmealOrderInfo> setmealOrderInfos = reportDao.getSetmealOrderInfo();
        List<String> names = setmealOrderInfos.stream().map(SetmealOrderInfo::getName).collect(Collectors.toList());
        return new SetmealReportVO(names,setmealOrderInfos);
    }

    /**
     * 套餐预约占⽐
     *
     * @return
     */
    @Override
    public List<Map<String, Objects>> countBySetmeal() {
        return reportDao.countBySetMeal();
    }

    /**
     * 根据月份统计用户数量
     *
     * @param months
     * @return
     */
    @Override
    public List<Integer> countByMonth(List<String> months) {
        List<Integer> resultLIst = new ArrayList<>();
        List<String> oneMonth = Arrays.asList("01", "03", "05", "07", "08", "10", "12");

        for (String month : months) {
            String endDate = month + "30";
            if (month.contains("02")) {
                endDate = month + ".28";
            } else if (oneMonth.contains(month)) {
                endDate = month + "31";
            }
            Long count = reportDao.countByRegTimeBefore(endDate);
            resultLIst.add(count.intValue());
        }
        return resultLIst;
    }


    @Override
    public Number getBusinessData(LocalDateTime beginToday, LocalDateTime endToday, LocalDate beginWeek, LocalDate endWeek, LocalDate beginMonth, LocalDate endMonth) {
        Map map1 = new HashMap<>();
        map1.put("begin", beginToday);
        map1.put("end", endToday);
        map1.put("status", Order.ORDERSTATUS_YES);

        Map map2 = new HashMap<>();
        map2.put("begin", beginWeek);
        map2.put("end", endWeek);
        map2.put("status", Order.ORDERSTATUS_YES);

        Map map3 = new HashMap<>();
        map3.put("begin", beginMonth);
        map3.put("end", endMonth);
        map3.put("status", Order.ORDERSTATUS_YES);

        //获取今日新会员数
        Integer todayNewMember = reportDao.countByMap(map1);
        //获取本周新会员数
        Integer thisWeekNewMember = reportDao.countByMap(map2);
        //获取本月新会员数
        Integer thisMonthNewMember = reportDao.countByMap(map3);
        //获取所有会员
        Integer totalMember = reportDao.count();
        //获取今日预约人数
        Integer todayOrderNumber = reportDao.countByMap(map1);
        //获取本周预约人数
        Integer thisWeekOrderNumber = reportDao.countByMap(map2);
        //获取本月预约人数
        Integer thisMonthOrderNumber = reportDao.countByMap(map3);
        //获取今日到诊人数
        Integer todayVisitsNumber = reportDao.countVisitsByMap(map1);
        //获取本周到诊人数
        Integer thisWeekVisitsNumber = reportDao.countVisitsByMap(map2);
        //获取本月到诊人数
        Integer thisMonthVisitsNumber = reportDao.countVisitsByMap(map3);
        //获取热门套餐名及数量
        List<HotSetmeal> list = reportDao.getHotSetmeal();
        extracted(list);

        Number number = new Number();
        return number.builder()
                .hotSetmeal(list)
                .totalMember(totalMember)
                .todayNewMember(todayNewMember)
                .thisWeekNewMember(thisWeekNewMember)
                .thisMonthNewMember(thisMonthNewMember)
                .todayOrderNumber(todayOrderNumber)
                .thisWeekOrderNumber(thisWeekOrderNumber)
                .thisMonthOrderNumber(thisMonthOrderNumber)
                .todayVisitsNumber(todayVisitsNumber)
                .thisWeekVisitsNumber(thisWeekVisitsNumber)
                .thisMonthVisitsNumber(thisMonthVisitsNumber)
                .build();
    }

    @Override
    public void export(HttpServletResponse response) {
        //构造时间
        LocalDate beginMonth = LocalDate.now().minusDays(30);
        LocalDate endMonth = LocalDate.now().minusDays(1);
        LocalDate beginWeek = LocalDate.now().minusDays(7);
        LocalDate endWeek = LocalDate.now().minusDays(1);
        LocalDateTime beginToday = LocalDateTime.now().with(LocalTime.MIN);
        LocalDateTime endToday = LocalDateTime.now().with(LocalTime.MAX);

        //基于模板文件创建工作簿对象(excel文件对象)
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("template/report_template.xlsx");

        try {
            XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
            XSSFSheet sheet = workbook.getSheetAt(0);

            XSSFRow row1 = sheet.getRow(2); //获取填写日期的行号
            row1.getCell(5).setCellValue("时间" + beginMonth + "至" + endMonth);

            Map map1 = new HashMap<>();
            map1.put("begin", beginToday);
            map1.put("end", endToday);
            map1.put("status", Order.ORDERSTATUS_YES);

            Map map2 = new HashMap<>();
            map2.put("begin", beginWeek);
            map2.put("end", endWeek);
            map2.put("status", Order.ORDERSTATUS_YES);

            Map map3 = new HashMap<>();
            map3.put("begin", beginMonth);
            map3.put("end", endMonth);
            map3.put("status", Order.ORDERSTATUS_YES);

            //获取今日新会员数
            Integer todayNewMember = reportDao.countByMap(map1);
            XSSFRow row2 = sheet.getRow(4); //获取行号
            row2.getCell(5).setCellValue(todayNewMember);
            //获取本周新会员数
            Integer thisWeekNewMember = reportDao.countByMap(map2);
            XSSFRow row3 = sheet.getRow(5); //获取行号
            row3.getCell(5).setCellValue(thisWeekNewMember);
            //获取本月新会员数
            Integer thisMonthNewMember = reportDao.countByMap(map3);
            XSSFRow row4 = sheet.getRow(5); //获取行号
            row4.getCell(7).setCellValue(thisMonthNewMember);
            //获取所有会员
            Integer totalMember = reportDao.count();
            XSSFRow row5 = sheet.getRow(4); //获取行号
            row5.getCell(7).setCellValue(totalMember);
            //获取今日预约人数
            Integer todayOrderNumber = reportDao.countByMap(map1);
            XSSFRow row6 = sheet.getRow(7); //获取行号
            row6.getCell(5).setCellValue(todayOrderNumber);
            //获取本周预约人数
            Integer thisWeekOrderNumber = reportDao.countByMap(map2);
            XSSFRow row7 = sheet.getRow(8); //获取行号
            row7.getCell(5).setCellValue(thisWeekOrderNumber);
            //获取本月预约人数
            Integer thisMonthOrderNumber = reportDao.countByMap(map3);
            XSSFRow row8 = sheet.getRow(9); //获取行号
            row8.getCell(5).setCellValue(thisMonthOrderNumber);
            //获取今日到诊人数
            Integer todayVisitsNumber = reportDao.countVisitsByMap(map1);
            XSSFRow row9 = sheet.getRow(7); //获取行号
            row9.getCell(7).setCellValue(todayVisitsNumber);
            //获取本周到诊人数
            Integer thisWeekVisitsNumber = reportDao.countVisitsByMap(map2);
            XSSFRow row10 = sheet.getRow(8); //获取行号
            row10.getCell(7).setCellValue(thisWeekVisitsNumber);
            //获取本月到诊人数
            Integer thisMonthVisitsNumber = reportDao.countVisitsByMap(map3);
            XSSFRow row11 = sheet.getRow(9); //获取行号
            row11.getCell(7).setCellValue(thisMonthVisitsNumber);

            List<HotSetmeal> list = reportDao.getHotSetmeal();
            extracted(list);
            XSSFRow row12 = sheet.getRow(12);
            row12.getCell(4).setCellValue(list.get(0).getName());
            row12.getCell(5).setCellValue(list.get(0).getSetmeal_count());
            row12.getCell(6).setCellValue(String.valueOf(list.get(0).getProportion()));
            XSSFRow row13 = sheet.getRow(13);
            row13.getCell(4).setCellValue(list.get(1).getName());
            row13.getCell(5).setCellValue(list.get(1).getSetmeal_count());
            row13.getCell(6).setCellValue(String.valueOf(list.get(1).getProportion()));
            XSSFRow row14 = sheet.getRow(14);
            row14.getCell(4).setCellValue(list.get(2).getName());
            row14.getCell(5).setCellValue(list.get(2).getSetmeal_count());
            row14.getCell(6).setCellValue(String.valueOf(list.get(2).getProportion()));
            XSSFRow row15 = sheet.getRow(15);
            row15.getCell(4).setCellValue(list.get(3).getName());
            row15.getCell(5).setCellValue(list.get(3).getSetmeal_count());
            row15.getCell(6).setCellValue(String.valueOf(list.get(3).getProportion()));

            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setHeader("Content-Disposition", "attachment; filename=report_template.xlsx");
            //将工作簿对象写入到浏览器，实现文件下载
            ServletOutputStream outputStream = response.getOutputStream();
            workbook.write(outputStream);

            //关闭资源
            outputStream.close();
            workbook.close();
        } catch (Exception e) {
            log.info("报表导出失败：{}",e.getMessage());
        }
    }

    private static void extracted(List<HotSetmeal> list) {
        BigDecimal count = new BigDecimal(0);
        for (HotSetmeal hotSetmeal : list) {
            BigDecimal decimal = new BigDecimal(hotSetmeal.getSetmeal_count());
            count = count.add(decimal);
        }
        for (HotSetmeal hotSetmeal : list) {
            BigDecimal decimal = new BigDecimal(hotSetmeal.getSetmeal_count());
            hotSetmeal.setProportion(decimal.divide(count, 4, RoundingMode.HALF_UP));
        }
    }

}